100行代码教你爬取斗图网(Python多线程队列)
本篇阅读时间约为 6 分钟。
1
前言
根据之前写的两篇文章,想必大家对多线程和队列有了一个初步的了解,今天这篇文章就来实战一下,用多线程 + 队列 爬取斗图网的全网图片。
你还在为斗图找图片而烦恼吗?快来跟我一起 happy 吧!
PS:本文目的是抱以学习心态而分享,禁止用于非法以及商业途径,如有风险,一切后果自己承担!
2
成果演示
先来看看最后的成果:
启动程序后,可以发现目录下是同时出现 5 个主题图片(线程设置了 5 个,所以同时创建 5 个文件夹)的,每个主题文件夹下都有相应的图片。
3
确认需求
开始之前,先来看下要爬取的网站以及图片,对其进一步进行分析。
1. 要爬取的网站 - 斗图啦
2. 要爬取的内容,肯定就是图片啦
每个主题的详细图片:
从斗图啦主页点到详情页可以看到,每个主题下有好多图片,所以需求就是爬取 1 - 615 页每页中详情页的图片。
4
html 节点分析
首先,在斗图啦首页列表中一共有 615 页,每次点击不同页时,可以观察到地址的变化:
不难发现,点击第几页时,网页地址后面的 page 就是几。
分析好网站的分页后,可以按照正常流程的逻辑进行 HTML 源码的分析,打开 F12 ,让我们来一步步进行梳理。
1. 分析每页的主题 url 地址
比如第一页中,要爬取其下的所有主题,而每个主题下又有具体的详情图片。所以第一步需要分析点击每个主题后的 url 地址。如下图:
这样一来,确定了第一页中,所有主题的具体详情页地址:
2. 分析每个主题下详情页的各个图片地址
用第一个企鹅表情举例,当我们点入到此主题后,F12继续分析每个图片的具体地址:
再次分析,可以发现,所有图片其实结构都一样,只需要提取下图的图片地址即可完成:
3. 思维导图爬取思路
5
代码设计思路
上面分析完,接下来讲下笔者的设计思路,代码不唯一,爬取的思路提供给大家了,也可自行先写一个玩玩看,然后在对比咱们写的代码有什么不同处。。
6
部分代码讲解
来简单的看部分代码:
def main():
print('程序开始!')
thread_nums = 5 # 开启 5 个线程
for main_url in range(1, 615):
url = f'https://www.doutula.com/article/list/?page={main_url}'
DouTuLaSpider.url_queue.put(url)
doutu = DouTuLaSpider()
# 开启多线程
for i in range(thread_nums):
thread = threading.Thread(target=doutu.run)
thread.start()
thread.join()
print('程序结束...')
def run(self):
""" 通过队列来实现多线程的有序性,从第 1 页到第 614 页有序处理 """
try:
while 1:
url_queue = DouTuLaSpider.url_queue
if url_queue.qsize() == 0:
break
else:
main_url = url_queue.get()
html = self.__crawl_html(main_url)
self.__control_speed() # 加延时
self.__analysis_main_url(html) # 分析主节点
except Exception as e:
import traceback
traceback.print_exc()
入口地方,开启 5 个线程,分别将所有页数的地址放入队列中,然后让线程去队列中有序的获取分页的地址。
如果有细看代码的同学,会发现上面的代码是 1-614 页,因为代码是前天写的,那会儿还只有 614 ,斗图啦网站每日都有更新哟。。
简单的说下为什么要用队列?就是因为有序,多线程下,如果不引用队列的话,有可能会出现爬取重复的url地址呀。。。不理解的话想想这个问题:你怎么知道哪个是你爬取过的的地址呢?
其余的具体提取操作代码就不放了。
当然,我们是为了学习,而不是为了攻击人家服务器。。。爬取的时候该控制速度就要控制速度,在源码中已经对应提供了。而笔者这里作为演示,也没有全爬取,就是爬取了一小部分而已。
7
总结
如果有想要全部代码的同学,老规矩,后台回复 斗图啦,完整代码已经放到了 github 上了。
关于多线程和队列不理解的同学,欢迎看下之前写的两篇文章。如果有哪里不懂的,欢迎留言区留言交流。
长按关注
公众号名称:咪哥杂谈
一个咪咪怪的公众号
长按二维码关注哦!